#include <iostream>
#include "boost_opt_util.h"
#include <boost/asio.hpp>
#include "trace.h"
#include "localcapture.h"
#include "liveserver.h"

int main(int argc, char *argv[])
{
    boost::program_options::options_description cmdline("Command line options");
    cmdline.add_options()
            ("help,h","show help message")
            ("port,p",
             boost::program_options::value<unsigned int>()->default_value(10086),
             "Main TCP connection port. For network commands.")
            ;
    boost::program_options::variables_map parameter_map = boost_opt_check(cmdline, argc, argv);

    const unsigned int CMDPORT = parameter_map["port"].as<unsigned int>();
    char hostname[32];
    gethostname(hostname, sizeof(hostname));

    try
    {
        using namespace boost::asio::ip;
        boost::asio::io_service initIos;
        tcp::acceptor initAcceptor(initIos, tcp::endpoint(tcp::v4(), CMDPORT));
        TRACE(1, "%s: Main Server is Ready on Port %d.\n", hostname, CMDPORT);
        tcp::iostream cmdStream;
        initAcceptor.accept(*cmdStream.rdbuf());
        TRACE(1, "%s: Connection accepted.\n", hostname);
        LocalCapture *capture;
        LiveServer *live;
        const int LIVEPORT = 9696;
        cmdStream << std::string("REDY\n");

        std::string mainCmd;
        double initShutter, initGain;
        unsigned int initFps;

        //This step is incorrect. Only for PF.
        cmdStream >> mainCmd >> initFps >> initShutter >> initGain;
        cmdStream.get();

        if(mainCmd=="ENPF")
        {
            TRACE(1, "%s: Start PF command received. FPS = %d, Shutter = %f, Gain = %f\n", hostname, initFps, initShutter, initGain);
            capture = new LocalCapture(hostname,initFps,0,initShutter,initGain);
            capture -> run();

            while(!capture->checkRunning())
            {
                //LocalCapture not ready yet
            }
            cmdStream << "PFRY " << capture->getFps() << std::endl;
            TRACE(1, "%s: ProFUSION ready message sended.\n", hostname);
        }

        const unsigned int MAINPORT = 10000;
        boost::asio::io_service mainIos;
        tcp::acceptor mainAcceptor(mainIos, tcp::endpoint(tcp::v4(), MAINPORT));
        TRACE(1, "%s: Init finished. Now listening on port %d.\n", hostname, MAINPORT);
        for(;;)
        {
            TRACE(1, "%s: mainAcceptor is waiting\n", hostname);
            tcp::iostream mainStream;
            mainAcceptor.accept(*mainStream.rdbuf());
            for(std::string line;std::getline(mainStream,line);)
            {
                if(line.empty() || line[0]=='\r')
                {
                    continue;
                }
                std::istringstream iss(line);
                std::string cmd;
                iss >> cmd;
                if(cmd=="ENLV")
                {
                    TRACE(1, "%s: Start Live command received.\n", hostname);
                    live = new LiveServer(hostname,capture,LIVEPORT,capture->getFps());
                    live->startLiveServer();
                    while(!live->checkRunning())
                    {
                        //LiveServer not ready yet
                    }
                    mainStream << "LVRY " << LIVEPORT << std::endl;
                    TRACE(1, "%s: Live ready message sended.\n", hostname);
                }
                else if(cmd=="ENCP")
                {
                    TRACE(1, "%s: Start Capture command received.\n", hostname);
                    timestamp_t startts = 0;
                    unsigned int frames = 0;
                    std::string fname;
                    iss >> startts >> frames >> fname;
                    timestamp_t realstart = 0;
                    if(startts==0)
                    {
                        //start now
                        TRACE(1,"%s: Start Capturing Now\n", hostname);
                        realstart = capture->startCapture(frames,fname, 8);

                    }
                    else
                    {
                        //start on time
                        realstart = capture->startCapture(startts,frames,fname, 8);
                    }
                    if(realstart==0)
                    {
                        TRACE(1,"%s: Capture cannot start.\n", hostname);
                    }
                    else
                    {
                        TRACE(1,"%s: Capture will start on %llu.\n",hostname, realstart);
                    }
                    mainStream << "CPSR " << realstart << std::endl;
                    TRACE(1, "%s: Capture start message sended.\n", hostname);
                }
            }

        }
    }
    catch(std::exception &e)
    {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}
